/*
 * @Author: cl
 * @Description: 装饰器
 * @Date: 2023-03-30 08:31:43
 * @LastEditTime: 2023-07-20 14:11:21
 * @FilePath: \jsnode\typescript\decorator.ts
 * @LastEditors: chenli chenli@kcwl.com
 */
// import "reflect-metadata";
/************************类装饰器*******************************/
const classDec: ClassDecorator = (target: Function) => {
  target.prototype.myClassName = "类装饰器";
  target.prototype.getClassName = <T>(params: T, param2: number) => {
    console.log(`我是方法里的${params}${param2}`);
    return params;
  };
};

@classDec
class MyClassD {}

let myClassD = new MyClassD();

// console.log(myClassD)
// console.log((myClassD as any).myClassName)
// console.log((myClassD as any).getClassName(123,'zhang'));

/************************方法装饰器*******************************/
//普通方法装饰器
const methodDec: MethodDecorator = (
  target,
  propertyKey,
  descriptor: PropertyDescriptor
) => {
  const method = descriptor.value;
  descriptor.value = () => {
    console.log(`重写方法`,target,propertyKey,descriptor);
  };
};
//静态方法装饰器
const staticMethodDec: MethodDecorator = (
  target,
  propertyKey,
  descriptor: PropertyDescriptor
) => {
  const method = descriptor.value;
  descriptor.value = () => {
    console.log(`重写静态方法`);
  };
};

class MyMethod {
  @methodDec
  public showMethod() {
    console.log(`来吧展示普通方法`);
  }
  @staticMethodDec
  public static showStaticMethod() {
    console.log(`来吧展示静态方法`);
  }
}

let myMethodD = new MyMethod();
// myMethodD.showMethod();
// console.log(myMethodD)
// myMethodD.showMethod()

// MyMethod.showStaticMethod()
/************************属性参数装饰器*******************************/
const proDec: PropertyDecorator = (target, propertyKey) => {
  let myvalue: string;
  console.log('proDec');
  Object.defineProperty(target, propertyKey, {
    get() {
      return myvalue.toLowerCase()+"--------";
    },
    set(v) {
      console.log('set');
      myvalue = v;
    },
  });
};
{
  class Student {
    @proDec
    public name: string;

    public age: number;
    constructor(n: string, a: number) {
      this.name = n;
      this.age = a;
    }
    say() {
      console.log(`${this.name}age is ${this.age}`);
    }
  }
  
  let xiaogang = new Student("ZHANG", 19);
  xiaogang.say()
  console.log(xiaogang.name)
}
/************************装饰器工厂*******************************/

const facDec = (params: string): ClassDecorator => {
  return (fun: Function) => {
    fun.prototype.say = () => {
      console.log(`i say${params}`);
    };
  };
};

@facDec("世界和平")
class MyFacDec {
  public title: string;
  say() {}
}

let myFacDec = new MyFacDec();
// myFacDec.say();

// Reflect.defineMetadata("myname", "12", myFacDec,'title');
// console.log(Reflect.getMetadata("myname",myFacDec,'title'))


